home *** CD-ROM | disk | FTP | other *** search
- /* libcmap2.c - support routines for color rows
- **
- ** Copyright (C) 1994 Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
- #include "ppmcmap2.h"
-
-
- colorhash_table
- ppm_colorrowtocolorhash(colorrow, ncolors)
- pixel *colorrow;
- int ncolors;
- {
- colorhash_table cht;
- int i;
-
- cht = ppm_alloccolorhash();
- for( i = 0; i < ncolors; i++ ) {
- if( ppm_lookupcolor(cht, &colorrow[i]) < 0 ) {
- if( ppm_addtocolorhash(cht, &colorrow[i], i) < 0 )
- pm_error("out of memory adding to hash table");
- }
- }
- return cht;
- }
-
-
- pixel *
- ppm_computecolorrow(pixels, cols, rows, maxcolors, ncolorsP)
- pixel **pixels;
- int cols, rows, maxcolors;
- int *ncolorsP;
- {
- int ncolors, row, col;
- colorhash_table cht;
- pixel *pixrow;
-
- pixrow = ppm_allocrow(maxcolors);
- cht = ppm_alloccolorhash(); ncolors = 0;
- for( row = 0; row < rows; row++ ) {
- for( col = 0; col < cols; col++ ) {
- if( ppm_lookupcolor(cht, &pixels[row][col]) < 0 ) {
- if( ncolors >= maxcolors ) {
- ppm_freerow(pixrow);
- pixrow = (pixel *)0;
- ncolors = -1;
- goto fail;
- }
- if( ppm_addtocolorhash(cht, &pixels[row][col], ncolors) < 0 )
- pm_error("out of memory adding to hash table");
- pixrow[ncolors] = pixels[row][col];
- ++ncolors;
- }
- }
- }
- fail:
- ppm_freecolorhash(cht);
-
- *ncolorsP = ncolors;
- return pixrow;
- }
-
-
- pixel *
- ppm_mapfiletocolorrow(file, maxcolors, ncolorsP, maxvalP)
- FILE *file;
- int maxcolors;
- int *ncolorsP;
- pixval *maxvalP;
- {
- int cols, rows, format, row, col, ncolors;
- pixel *pixrow, *temprow;
- colorhash_table cht;
-
- pixrow = ppm_allocrow(maxcolors);
-
- ppm_readppminit(file, &cols, &rows, maxvalP, &format);
- temprow = ppm_allocrow(cols);
- cht = ppm_alloccolorhash(); ncolors = 0;
- for( row = 0; row < rows; row++ ) {
- ppm_readppmrow(file, temprow, cols, *maxvalP, format);
- for( col = 0; col < cols; col++ ) {
- if( ppm_lookupcolor(cht, &temprow[col]) < 0 ) {
- if( ncolors >= maxcolors ) {
- ppm_freerow(pixrow);
- pixrow = (pixel *)0;
- ncolors = -1;
- goto fail;
- }
- if( ppm_addtocolorhash(cht, &temprow[col], ncolors) < 0 )
- pm_error("out of memory adding to hash table");
- pixrow[ncolors] = temprow[col];
- ++ncolors;
- }
- }
- }
- fail:
- ppm_freecolorhash(cht);
- ppm_freerow(temprow);
-
- *ncolorsP = ncolors;
- return pixrow;
- }
-
-
- static int
- pixel_cmp(a, b)
- void *a, *b;
- {
- pixel *p1 = (pixel *)a, *p2 = (pixel *)b;
- int diff;
-
- diff = PPM_GETR(*p1) - PPM_GETR(*p2);
- if( diff == 0 ) {
- diff = PPM_GETG(*p1) - PPM_GETG(*p2);
- if( diff == 0 )
- diff = PPM_GETB(*p1) - PPM_GETB(*p2);
- }
- return diff;
- }
-
- static int (*custom_cmp) ARGS((pixel *, pixel *));
-
- static int
- custom_stub(a, b)
- void *a, *b;
- {
- return (*custom_cmp)((pixel *)a, (pixel *)b);
- }
-
-
- void
- ppm_sortcolorrow(colorrow, ncolors, cmpfunc)
- pixel *colorrow;
- int ncolors;
- int (*cmpfunc) ARGS((pixel *, pixel *));
- {
- if( cmpfunc ) {
- custom_cmp = cmpfunc;
- qsort((void *)colorrow, ncolors, sizeof(pixel), custom_stub);
- }
- else
- qsort((void *)colorrow, ncolors, sizeof(pixel), pixel_cmp);
- }
-
-
-
- int
- ppm_addtocolorrow(colorrow, ncolorsP, maxcolors, pixelP)
- pixel *colorrow;
- int *ncolorsP;
- int maxcolors;
- pixel *pixelP;
- {
- int i;
- pixval r, g, b;
-
- r = PPM_GETR(*pixelP);
- g = PPM_GETG(*pixelP);
- b = PPM_GETB(*pixelP);
-
- for( i = 0; i < *ncolorsP; i++ ) {
- if( PPM_GETR(colorrow[i]) == r &&
- PPM_GETG(colorrow[i]) == g &&
- PPM_GETB(colorrow[i]) == b )
- return i;
- }
-
- i = *ncolorsP;
- if( i >= maxcolors )
- return -1;
- colorrow[i] = *pixelP;
- ++*ncolorsP;
- return i;
- }
-
-
- int
- ppm_findclosestcolor(colormap, ncolors, pP)
- pixel *colormap;
- int ncolors;
- pixel *pP;
- {
- /* Search colormap for closest match. */
- /* algorithm taken from ppmquant.c -IUW */
- register int i, r1, g1, b1;
- int ind;
- long dist;
-
- r1 = PPM_GETR(*pP);
- g1 = PPM_GETG(*pP);
- b1 = PPM_GETB(*pP);
- dist = 2000000000;
- for( i = 0; i < ncolors; i++ ) {
- register int r2, g2, b2;
- long newdist;
-
- r2 = PPM_GETR(colormap[i]);
- g2 = PPM_GETG(colormap[i]);
- b2 = PPM_GETB(colormap[i]);
- newdist = ( r1 - r2 ) * ( r1 - r2 ) +
- ( g1 - g2 ) * ( g1 - g2 ) +
- ( b1 - b2 ) * ( b1 - b2 );
-
- if( newdist < dist ) {
- ind = i;
- dist = newdist;
- }
- }
- return ind;
- }
-
-
- void
- #if __STDC__
- ppm_colorrowtomapfile(FILE *ofp, pixel *colormap, int ncolors, pixval maxval)
- #else
- ppm_colorrowtomapfile(ofp, colormap, ncolors, maxval)
- FILE *ofp;
- pixel *colormap;
- int ncolors;
- pixval maxval;
- #endif
- {
- int i;
-
- ppm_writeppminit(ofp, ncolors, 1, maxval, 1);
- for( i = 0; i < ncolors; i++ )
- ppm_writeppmrow(ofp, &colormap[i], 1, maxval, 1);
- }
-
-